
package stcu;

import stcu.robjects.*;
import com.nvlled.route.*;

import java.util.*;

public class GroupDemux {
    private ObjectRouter router;
    private Multimap<String, Group> groupMap;

    public GroupDemux(ObjectRouter router) {
        this.router = router;
        groupMap = new Multimap<String, Group>();

        subscribe();
    }

    private void subscribe() {
        // type erasure bites
        router.subscribe(GroupJoin.class, new GroupJoinReceiver());
        router.subscribe(GroupDel.class, new GroupDelReceiver());
        router.subscribe(GroupSend.class, new GroupSendReceiver());
        router.subscribe(GroupLeave.class, new GroupLeaveReceiver());
        router.subscribe(GroupMessage.class, new GroupMessageReceiver());
        router.subscribe(MemberAdd.class, new MemberAddReceiver());
        router.subscribe(MemberDel.class, new MemberDelReceiver());
        router.subscribe(MemberList.class, new MemberListReceiver());
    }

    public void register(Group group) {
        groupMap.add(group.getId(), group);
    }

    public void unregister(Group group) {
        groupMap.remove(group.getId(), group);
    }

    public Set<Group> getSubscribedGroups() {
        Set<Group> groups = new HashSet<Group>();
        for (String type: groupMap.keys()) {
            for (Group group: groupMap.getValues(type)) {
                groups.add(group);
            }
        }
        return groups;
    }


    //  This boilerplate is making my head steam.
    //  If anyone knows a better solution, please do change.
    //  If it involves string munging, never mind.


    class GroupJoinReceiver implements ObjectReceiver<GroupJoin> {
        public void receive(GroupJoin obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }

    class GroupDelReceiver implements ObjectReceiver<GroupDel> {
        public void receive(GroupDel obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }

    class GroupLeaveReceiver implements ObjectReceiver<GroupLeave> {
        public void receive(GroupLeave obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }

    class MemberListReceiver implements ObjectReceiver<MemberList> {
        public void receive(MemberList obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }

    class GroupMessageReceiver implements ObjectReceiver<GroupMessage> {
        public void receive(GroupMessage obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }

    class GroupSendReceiver implements ObjectReceiver<GroupSend> {
        public void receive(GroupSend obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }

    class MemberAddReceiver implements ObjectReceiver<MemberAdd> {
        public void receive(MemberAdd obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }

    class MemberDelReceiver implements ObjectReceiver<MemberDel> {
        public void receive(MemberDel obj) {
            Collection<Group> groups = groupMap.getValues(obj.getGroupId());
            for (Group group: groups) {
                group.receive(obj);
            }
        }
    }
}

